/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package client.controller;

import client.network.NetworkEventsDispatcher;
import client.network.NetworkClient;
import client.controller.events.VisitorCreatedEvent;
import client.controller.events.VisitorDeletedEvent;
import client.controller.events.VisitorGuideEvent;
import client.controller.events.VisitorListener;
import client.controller.events.VisitorUpdatedEvent;
import client.ihm.view.VisitorLayer2D;
import client.ihm.view.VisitorsView;
import common.model.Visitor;
import common.model.message.GuideMessage;
import common.model.message.UpdateMessage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 *
 * @author nicolas
 */
public class VisitorsLayerController implements VisitorListener {
    final Logger logger = LoggerFactory.getLogger(VisitorsLayerController.class);
    private VisitorsView view;
    private Visitor localVisitor;
    private NetworkClient networkClient = null;

    public VisitorsLayerController(VisitorsView view, Visitor localVisitor, NetworkClient networkClient) {
        this.view = view;
        this.localVisitor = localVisitor;
        this.networkClient = networkClient;
        NetworkEventsDispatcher.getApplicationEventsDispatcher().addVisitorListener(this);

        view.addVisitor(localVisitor);
    }

    public void visitorCreated(VisitorCreatedEvent evt) {
        logger.debug("received VisitorCreatedEvent : {}", evt.getVisitor().getCompleteInfo());
        view.addVisitor(evt.getVisitor());
    }

    public void visitorUpdated(VisitorUpdatedEvent evt) {
        logger.debug("received VisitorUpdatedEvent : {}", evt.getVisitor().getCompleteInfo());
        view.updateVisitor(evt.getVisitor());
    }

    public void visitorDeleted(VisitorDeletedEvent evt) {
        logger.debug("received VisitorDeletedEvent : {}", evt.getVisitor().getCompleteInfo());
        view.deleteVisitor(evt.getVisitor());
    }

    public void computeKeyEvent(char key) {
        if (key == 'z')
        {   //If the localVisitor is within the guide perimeter, we check if he's going outta the perimeter
            if( isVisitorCloseToGuide(localVisitor) )
            {
                Visitor tmp = new Visitor();
               //Move forward
                tmp.setX(localVisitor.getX() + Math.cos(Math.toRadians(localVisitor.getRotation())));
                tmp.setZ(localVisitor.getZ() + Math.sin(Math.toRadians(localVisitor.getRotation())));
                if( isVisitorCloseToGuide(tmp) )
                {   //Place the local visitor where it should be after the move
                    localVisitor.setX(tmp.getX());
                    localVisitor.setZ(tmp.getZ());
                    System.err.println("Still inside perimeter");
                }
                else logger.info("Would go outside the guide perimeter !!!");
            }
            else
            {
                //Move forward
                localVisitor.setX(localVisitor.getX() + Math.cos(Math.toRadians(localVisitor.getRotation())));
                localVisitor.setZ(localVisitor.getZ() + Math.sin(Math.toRadians(localVisitor.getRotation())));
            }

            view.updateVisitor(localVisitor);
            networkClient.sendMessage(new UpdateMessage(localVisitor));

        } else if (key == 'q') {
            //Turn left but center of rotation is not the center of the rectangle
            localVisitor.setRotation(localVisitor.getRotation() - 10);
            view.updateVisitor(localVisitor);
            networkClient.sendMessage(new UpdateMessage(localVisitor));
        } else if (key == 'd') {
            //Turn right
            localVisitor.setRotation(localVisitor.getRotation() + 10);
            view.updateVisitor(localVisitor);
            networkClient.sendMessage(new UpdateMessage(localVisitor));
        }
    }

    public void visitorGuide(VisitorGuideEvent evt) {
        if(this.localVisitor.getUserName().equals(evt.getUserName())){
            this.localVisitor.setGuide(evt.isGuide());
        }
        view.setGuide(evt.getUserName(), evt.isGuide());
    }

    public boolean isVisitorCloseToGuide(Visitor vs)
    {
        if( ((VisitorLayer2D)view).getGuide() != null )
        {
            double dist = ((VisitorLayer2D)view).getGuide().getDistFrom(vs);
            if( dist*2 < ((VisitorLayer2D)view).getCircleSize() ) return true;
        }
        //If there is no guide we consider we're never close to one
        return false;
    }
}